﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using CSA.Lib;

namespace CSA.Operator
{
    public class ReplaceOperator : ICSOperator
    {

        #region Fields
        CSPopulation m_OperatePopulation=null;   
        String m_CurUsedFunctionName = "";
        Hashtable m_FunctionNames = new Hashtable();
        #endregion

        #region Properties

        public String Name
        {
            get { return "ReplaceOperator"; }
        }

        public String Caption
        {
            get { return global::CSA.Operator.TextString.ReplaceOperatorCaption; }
        }

        public String Description
        {
            get { return global::CSA.Operator.TextString.ReplaceOperatorDes; }
        }

        public String Library
        {
            get { return "CSA.Operator"; }
        }

        public Hashtable Get_Parameters(String nFunctionName)
        {
            String nValidateName = "";
            if (nFunctionName.Trim() == "" || !m_FunctionNames.Contains(nFunctionName))
            {
                nValidateName = "DefaultReplaceFunction";

            }
            else
            {
                nValidateName = nFunctionName;
            }
            CSFuntionInfo nDefulatParas = (CSFuntionInfo)m_FunctionNames[nValidateName];
            return nDefulatParas.Parameters;
        }

        public OperatorType OperatorType
        {
            get { return OperatorType.enumReplacementPopOperator; }
        }
        public Hashtable FunctionNames
        {
            get { return m_FunctionNames; }
        }

        public bool UseCustomAntibodyOperator
        {
            get { return false; }
        }

        public CSFuntionInfo CustomAntibodyOperator
        {
            get { return null; }
            set { }
        }

        #endregion

        #region Methods

        public ReplaceOperator()
        {
            InitialParameters();
        }
        public bool Execute(CSPopulation nOperatePopulation, ref String nErrorStr, String nMethodName = "")
        {      
            m_OperatePopulation = nOperatePopulation;
              if (nMethodName.Trim() == "" || !m_FunctionNames.Contains(nMethodName))
            {
                m_CurUsedFunctionName = "DefaultReplaceFunction";
            }
            else
            {
                m_CurUsedFunctionName = nMethodName;
            }
            CSFuntionInfo nDefulatParas = (CSFuntionInfo)m_FunctionNames[m_CurUsedFunctionName];
            if (m_CurUsedFunctionName == "DefaultReplaceFunction")
            {
                CSParameter ReplacePopSize = (CSParameter)nDefulatParas.Parameters["ReplaceRatio"];
                Double nReplacePopRate =Convert.ToDouble(ReplacePopSize.Value.ToString());
                ICSOptimizationProblem nCurProblem = nOperatePopulation.ProblemInfo;
                int nPopSize = nOperatePopulation.PopulationSize;
                double nReplaceNum = nReplacePopRate * nPopSize;
                int nReplacePopSize = (int)Math.Round(nReplaceNum);
                List<CSAntibody> nNewPop = new List<CSAntibody>();
                for (int i = 0; i < nReplacePopSize; i++)
                {
                    CSAntibody nNewAb = nCurProblem.CreateAb();
                    nCurProblem.EvaluateAb(ref nNewAb);
                    nNewPop.Add(nNewAb);
                }
                if (nCurProblem.Objectives.Count > 0 && nCurProblem.MultiObjectiveProcessor != null)
                {
                    nCurProblem.MultiObjectiveProcessor.Execute(m_OperatePopulation, ref nErrorStr);
                }
                nNewPop.Sort(new AntibodyCompare());
                List<CSAntibody> nNonMemoryPop = nOperatePopulation.Antibodies;
                Int32 nNonMemoryIt = nNonMemoryPop.Count - 1;
                CSAntibody nMinNonMemory = nNonMemoryPop[nNonMemoryIt];
                Int32 nNewMemoryIt;
                for (nNewMemoryIt = 0; nNewMemoryIt < nNewPop.Count; )
                {
                    CSAntibody nCurAntibody = nNewPop[nNewMemoryIt];
                    nMinNonMemory = nNonMemoryPop[nNonMemoryIt];
                    if (nCurAntibody.Affinity <= nMinNonMemory.Affinity)
                    {
                        break;
                    }
                    else
                    {
                        nNonMemoryPop[nNonMemoryIt] = nCurAntibody;
                        ++nNewMemoryIt;
                        if (nNonMemoryIt == 0)
                        {
                            break;
                        }
                        nNonMemoryIt--;
                    }
                }
                nNewPop.Clear();
                nNonMemoryPop.Sort(new AntibodyCompare());
            }
            return true;
        }

        public void InitialParameters()
        {
            m_FunctionNames.Clear();
            CSFuntionInfo m_DefaultFunctionInfo = new CSFuntionInfo();
            m_DefaultFunctionInfo.Caption = global::CSA.Operator.TextString.DefaultFunction;
            m_DefaultFunctionInfo.Description = global::CSA.Operator.TextString.DefaultReplaceFunctionDes;
            m_DefaultFunctionInfo.Name = "DefaultReplaceFunction";
            Hashtable nStandardFunctionPara = new Hashtable();
            float nDefaultUpdateRate = 0.2F;
            CSParameter UpdateRate = new CSParameter();
            UpdateRate.Type = ParameterType.enumFloat;
            UpdateRate.Caption = global::CSA.Operator.TextString.ReplaceRatioCaption;
            UpdateRate.Description = global::CSA.Operator.TextString.ReplaceRatioDes;
            UpdateRate.Name = "ReplaceRatio";
            UpdateRate.Value = nDefaultUpdateRate;
            UpdateRate.DomainType = enumParasDomain.enumDomainExtent;
            string low = "0.01";
            string up = "0.8";
            List<string> nDomains = new List<string>();
            nDomains.Add(low);
            nDomains.Add(up);
            UpdateRate.DomainValues = nDomains;
            nStandardFunctionPara.Add("ReplaceRatio", UpdateRate);
            m_DefaultFunctionInfo.Parameters = nStandardFunctionPara;
            m_FunctionNames.Add(m_DefaultFunctionInfo.Name, m_DefaultFunctionInfo);
        }

        #endregion
    }
}
